package com.ironone.mediaplayerdemo;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.ConnectivityManager;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;


public class MyMediaPlayerService extends Service {

	public static MediaPlayer mediaPlayer;

	BroadcastReceiver br_ConnectivityCheck;
	BroadcastReceiver br_HeadsetCheck;
	BroadcastReceiver br_commonReceiver;

	NotificationManager mNotificationManager;
	boolean isError = false;
	int isError_ErrorCode = 0;

	@Override
	public void onCreate() {
		try {
			super.onCreate();
			mediaPlayer = MyMediaPlayer.getMediaPlayerInstance();
			mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);

			myMediaPlayerActivityCallbacks();

			getMediaPlayerAudioFocus(getApplicationContext());

			br_ConnectivityCheck = new BroadcastReceiver(){
				@Override
				public void onReceive(Context context, Intent intent) {
					boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
					if (noConnectivity) {
						if (MyMediaPlayer.getIsPlayerOnBackground()) {  // Player NOT on top of screen
							MyMediaPlayer.resetAndPrepareMediaPlayer();
						} else {
							MyMediaPlayer.resetAndPrepareMediaPlayer();

							Intent intent1 = new Intent(MyMediaPlayer.ACT_NOTIFICATION);
							intent1.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.CONNECTIVITY.ordinal()); // value == 0
							sendBroadcast(intent1);
						}
					}
				}
			};
			registerReceiver(br_ConnectivityCheck, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));

			br_HeadsetCheck = new BroadcastReceiver(){
				@Override
				public void onReceive(Context context, Intent intent) {
					int state = intent.getIntExtra("state", 0);
					switch (state) {
					case 0: // Head-set is unplugged / unmounted			
						if (MyMediaPlayer.getIsPlayerOnBackground()) {  // Player NOT on top of screen
							MyMediaPlayer.pauseMediaPlayer();
						} else {
							MyMediaPlayer.pauseMediaPlayer();

							Intent intent2 = new Intent(MyMediaPlayer.ACT_NOTIFICATION);
							intent2.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.HEADSET_UNMOUNTED.ordinal()); // value == 1
							sendBroadcast(intent2);
						}
						break;
					case 1: // Head-set is plugged
						break;
					default:
					}
				}
			};
			registerReceiver(br_HeadsetCheck, new IntentFilter(Intent.ACTION_HEADSET_PLUG));


			mediaPlayer.setOnPreparedListener(new OnPreparedListener() {

				public void onPrepared(MediaPlayer mp) {
					try {
						if (MyMediaPlayer.getIsPlayerOnBackground()) { // Player NOT on top of screen
							if(MyMediaPlayer.getMediaPlayerStatus() != MediaPlayerStatus.FORCE_PAUSED){
								MyMediaPlayer.playMediaPlayer();						
							}
						} else {
							MyMediaPlayer.playMediaPlayer();
							
							Intent intent1 = new Intent(MyMediaPlayer.ACT_NOTIFICATION);
							intent1.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.ON_PREPARED.ordinal()); // value == 3
							sendBroadcast(intent1);
						}
					}catch (Exception e) {
						//playButton.setChecked(false);
						//MyMediaPlayer.releaseMediaPlayer();
					}
				}
			});

			mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

				@Override
				public void onCompletion(MediaPlayer arg0) {					
					if (MyMediaPlayer.getIsPlayerOnBackground()) { // Player NOT on top of screen
						if(isError){
							MyMediaPlayer.resetMediaPlayer();
						}else {
							MyMediaPlayer.resetAndPrepareMediaPlayer();	
						}
					}else {
						if(isError){
							MyMediaPlayer.resetMediaPlayer();
						}else {
							MyMediaPlayer.resetAndPrepareMediaPlayer();	
						}
						
						Intent intent1 = new Intent(MyMediaPlayer.ACT_NOTIFICATION);
						intent1.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.ON_COMPLETION.ordinal()); // value == 5
						intent1.putExtra("isError", isError);
						intent1.putExtra("isError_ErrorCode", isError_ErrorCode);
						sendBroadcast(intent1);
					}
				}
			});

			mediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {

				@Override
				public void onBufferingUpdate(MediaPlayer arg0, int percent) {

					if (MyMediaPlayer.getIsPlayerOnBackground()) { // Player NOT on top of screen
						if (percent == 100) {
							MyMediaPlayer.resetAndPrepareMediaPlayer();
						}
					}else {
						if (percent == 100) {
							MyMediaPlayer.resetAndPrepareMediaPlayer();
						}
						
						Intent intent1 = new Intent(MyMediaPlayer.ACT_NOTIFICATION);
						intent1.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.ON_BUFFERING_UPDATE.ordinal()); // value == 6
						intent1.putExtra("percent", percent);
						sendBroadcast(intent1);
					}
				}
			});

			mediaPlayer.setOnInfoListener(new OnInfoListener() {

				@Override
				public boolean onInfo(MediaPlayer mp, int what, int extra) {

					if (MyMediaPlayer.getIsPlayerOnBackground()) { // Player NOT on top of screen
					}else {
						Intent intent7 = new Intent(MyMediaPlayer.ACT_NOTIFICATION);
						intent7.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.ON_INFO.ordinal()); // value == 7
						intent7.putExtra("what", what);
						sendBroadcast(intent7);
					}
					return false;
				}
			});

			mediaPlayer.setOnErrorListener(new OnErrorListener() {

				@Override
				public boolean onError(MediaPlayer mp, int what, int extra) {
					isError = true;
					isError_ErrorCode = extra;
					return false;
				}
			});

		} catch (Exception e) {
		}
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		unregisterReceiver(br_ConnectivityCheck);
		unregisterReceiver(br_HeadsetCheck);
		unregisterReceiver(br_commonReceiver);
	}

	public static void getMediaPlayerAudioFocus(final Context context) {
		try {
			AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
			audioManager.requestAudioFocus(new OnAudioFocusChangeListener() {

				@Override
				public void onAudioFocusChange(int focusChange) {
					switch (focusChange) {
					case AudioManager.AUDIOFOCUS_GAIN:
						// Resume play-back
						if (MyMediaPlayer.getIsPlayerOnBackground()){
							if(MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.RELEASED || 
									MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.RESETED){
								MyMediaPlayer.prepareMediaPlayer();
							}else if (MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.PAUSED){
								MyMediaPlayer.playMediaPlayer();
							}
						}else {
							if(MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.RELEASED || 
									MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.RESETED){
								MyMediaPlayer.prepareMediaPlayer();
								
								Intent intent3 = new Intent(MyMediaPlayer.SVC_NOTIFICATION);
								intent3.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.PREPARE_PLAYER.ordinal()); // value == 3
								context.sendBroadcast(intent3);								
							}else if (MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.PAUSED){
								MyMediaPlayer.playMediaPlayer();
								
								Intent intent3 = new Intent(MyMediaPlayer.SVC_NOTIFICATION);
								intent3.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.PLAY_PLAYER.ordinal()); // value == 3
								context.sendBroadcast(intent3);	
							}
						}
						MyMediaPlayer.getMediaPlayerInstance().setVolume(1.0f, 1.0f);
						break;

					case AudioManager.AUDIOFOCUS_LOSS:
						// Lost focus for an unbounded amount of time: stop playback and release media player
						if (MyMediaPlayer.getMediaPlayerInstance().isPlaying() || MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.PLAYING){
							//MyMediaPlayer.releaseMediaPlayer();

							if (MyMediaPlayer.getIsPlayerOnBackground()){
								MyMediaPlayer.releaseMediaPlayer();
							}else {
								MyMediaPlayer.releaseMediaPlayer();

								Intent intent3 = new Intent(MyMediaPlayer.SVC_NOTIFICATION);
								intent3.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.AUDIO_FOCUS_LOST.ordinal()); // value == 3
								context.sendBroadcast(intent3);
							}
						}
						break;

					case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
						// Lost focus for a short time, but we have to stop
						// playback. We don't release the media player because playback
						// is likely to resume
						if (MyMediaPlayer.getMediaPlayerInstance().isPlaying() || MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.PLAYING){

							if (MyMediaPlayer.getIsPlayerOnBackground()){
								MyMediaPlayer.pauseMediaPlayer();
							}else{
								MyMediaPlayer.pauseMediaPlayer();

								Intent intent3 = new Intent(MyMediaPlayer.SVC_NOTIFICATION);
								intent3.putExtra(MyMediaPlayer.VALUE, MyMediaPlayerActivityNotifyStatus.AUDIOFOCUS_LOSS_TRANSIENT.ordinal()); // value == 3
								context.sendBroadcast(intent3);
							}
						}
						break;

					case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
						// Lost focus for a short time, but it's ok to keep playing
						// at an attenuated level
						if (MyMediaPlayer.getMediaPlayerInstance().isPlaying() || MyMediaPlayer.getMediaPlayerStatus() == MediaPlayerStatus.PLAYING)
							MyMediaPlayer.getMediaPlayerInstance().setVolume(0.1f, 0.1f);
						break;
					}
				}
			}, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void startNotificationOnStatusBar() {
		// Notification show in status bar
		NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
				this).setSmallIcon(R.drawable.icon).setContentTitle("TNL Radio").setContentText("content text");
		mBuilder.setPriority(2);

		// Creates an explicit intent for an Activity in your app
		Intent resultIntent = new Intent(this, MainActivity.class);
		//Intent resultIntent = this.getBaseContext().getIntent();

		TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
		// Adds the back stack for the Intent (but not the Intent itself)
		stackBuilder.addParentStack(MainActivity.class);
		// Adds the Intent that starts the Activity to the top of the stack
		stackBuilder.addNextIntent(resultIntent);

		PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
				PendingIntent.FLAG_UPDATE_CURRENT);
		mBuilder.setContentIntent(resultPendingIntent);
		mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		int mId = 0;
		// mId allows you to update the notification later on.
		mNotificationManager.notify(mId, mBuilder.build());
	}

	private void stopNotificationOnStatusBar() {
		// Notification clear in status bar
		mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		int mId = 0;
		mNotificationManager.cancel(mId);
	}

	
	private void myMediaPlayerActivityCallbacks() {
		try {
			br_commonReceiver = new BroadcastReceiver() {
				@Override
				public void onReceive(Context context, Intent intent) {
					int value = 6;
					if(intent == null)
						value = 6;
					else
						value = intent.getIntExtra(MyMediaPlayer.VALUE, 6); // 6 == RESET_N_PREPARE
					
					MyMediaPlayerServiceNotifyStatus whichView = MyMediaPlayerServiceNotifyStatus.values()[value];

					switch (whichView) {
					case GET_AUDIO_FOCUS :
						getMediaPlayerAudioFocus(getApplicationContext());
						break;

					case PREPARE_PLAYER :
						MyMediaPlayer.prepareMediaPlayer();
						break;

					case PLAY_PLAYER:
						MyMediaPlayer.playMediaPlayer();
						break;

					case PAUSE_PLAYER:
						MyMediaPlayer.pauseMediaPlayer();
						break;

					case RESET_PLAYER:
						MyMediaPlayer.resetMediaPlayer();
						break;

					case RESET_N_PREPARE:
						MyMediaPlayer.resetAndPrepareMediaPlayer();
						break;

					case RELEASE_PLAYER:
						MyMediaPlayer.releaseMediaPlayer();
						break;

					case START_NOTIFICATION:
						startNotificationOnStatusBar();
						break;

					case STOP_NOTIFICATION:
						stopNotificationOnStatusBar();
						break;

					default:
						//MyMediaPlayer.releaseMediaPlayer();
					}
				}
			};
			registerReceiver(br_commonReceiver, new IntentFilter(MyMediaPlayer.SVC_NOTIFICATION)); // ACT sending SERVICE notifications
		} catch (Exception e) {
			MyMediaPlayer.releaseMediaPlayer();			
		}
	}
}